package org.slusk.thynwor.util;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;

public class Csv2StdDeviation {

	/**
	 * @param args
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException {
//		DStore d = new DStore("test", 3, 3);
//		d.values[0][0] = 10;
//		d.values[0][1] = 11;
//		d.values[0][2] = 12;
//		d.values[1][0] = 100;
//		d.values[1][1] = 150;
//		d.values[1][2] = 200;
//		d.values[2][0] = 3000;
//		d.values[2][1] = 4000;
//		d.values[2][2] = 5000;
//
//		
//		d.calculateStdDeviations(0);
//		d.calculateStdDeviations(1);
//		d.calculateStdDeviations(2);
//		
//		ArrayList<DStore> data = new ArrayList<DStore>();
//		data.add(d);
//		
//		dumpToFile(data, "check.csv");
		
		doit(args);

	}
	
	private static void doit(String[] args) throws IOException {
 		String directory = args[0];
		String runName = args[1];
		String outFileName = args[2];
		ArrayList<DStore> data = initializeData(directory, runName);
		int gens = data.get(0).values.length;
		int cols = data.size();
		
		populateData(directory, runName, data, gens, cols);
		
		// for each gen, calculate std dev
		for (DStore dstore: data) {
			for (int gen = 0; gen < gens; gen++) {
				dstore.calculateStdDeviations(gen);
			}
		}
		
		// dump to file
		dumpToFile(data, outFileName);
	}

	/**
	 * @param directory
	 * @param runName
	 * @param run
	 * @param data
	 * @param gens
	 * @param cols
	 * @throws IOException
	 */
	public static void populateData(String directory, String runName, ArrayList<DStore> data, int gens, int cols) throws IOException {
		String folderName;
		int run = 1;
		
		// For each folder with run data
		folderName = runName + "_" + run;
		File file = new File(directory+"/"+folderName+"/allAggregate.csv");
		while (file.exists()) {
			// open all aggregate csv 
			
			SimpleCsv csv = new SimpleCsv(file);		
			
			// for each gen of each column, populate data for current run
			for (int gen = 1; gen < gens+1; gen++) {
				
				for (int col = 0, allAggCol = 1; col < cols; col++, allAggCol+=3) {
//					data.get(col).values[gen-1][run-1] = Double.parseDouble(csv.get(gen, allAggCol));
					data.get(col).setValue(gen-1, run-1, Double.parseDouble(csv.get(gen, allAggCol)));
				}
			}
			
			run++;
			folderName = runName + "_" + run;
			file = new File(directory+"/"+folderName+"/allAggregate.csv");
		}
	}


	private static void dumpToFile(ArrayList<DStore> data, String outFileName) throws IOException {
		BufferedWriter out = new BufferedWriter(new FileWriter(outFileName));
		int gens = data.get(0).stdDevs.length;
		
		out.write("Generation,");
		
		// write column headers
		for (DStore dstore : data) {
			out.write(dstore.columnName + "_StdDev");
			out.write(",");
		}
		
		out.write("\n");
		
		// write data
		for (int gen = 0; gen < gens; gen++) {
			out.write(gen + ",");
			for (DStore dstore : data) {
				out.write(dstore.stdDevs[gen]+",");
				
			}
			out.write("\n");
		}
		
		out.close();
	}


	private static ArrayList<DStore> initializeData(String directory, String runName) throws IOException {
		ArrayList<DStore> data = null;
		
		BufferedReader in = new BufferedReader(new FileReader(directory+"/"+runName+"/crga.csv"));
		
		// read column headers, generates names for each dstore
		String[] cols = in.readLine().split(",");
		data = new ArrayList<DStore>(cols.length-1);
		
		int gens = 0;
		String line;
		// count num gens
		while ((line = in.readLine()) != null) {
//			gens = Integer.parseInt(line.split(",")[0]);
			gens++;
		}
		
		in.close();
		
		// count num runs
		int runs = 1;
		File file = new File(directory+"/"+runName+"_"+runs);
		while (file.exists()) {
			runs++;
			file = new File(directory+"/"+runName+"_"+runs);
		}
		runs--;
		
		for (int i = 1; i < cols.length; i++) {
			data.add(new DStore(cols[i], gens, runs));
		}
		
		return data;
	}

}

class DStore {
	public String columnName;
	public double[][] values;	// generation x run
	public double[] stdDevs;
	
	public  DStore(String columnName, int numGens, int numRuns) {
		this.columnName = columnName;
		this.values = new double[numGens][numRuns];
		this.stdDevs = new double[numGens];
	}
	
	public void calculateStdDeviations(int gen) {
		double[] vals = new double[values[gen].length];
		double avg = Util.average(values[gen]);
		for (int i = 0; i < vals.length; i++) {
			vals[i] = Math.pow(values[gen][i] - avg, 2); 
		}
		
		stdDevs[gen] = Math.sqrt(Util.average(vals));
	}


	
	public void setValue(int generation, int run, double value) {
		values[generation][run] = value;
	}
}

